package seatechit.msbgateway.processor;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;

import seatechit.msbgateway.consumer.BaseConsumer;
import seatechit.msbgateway.consumer.EmailConsumer;
import seatechit.msbgateway.consumer.ErrorInfo;
import seatechit.msbgateway.consumer.SIBSConsumer;
import seatechit.msbgateway.consumer.SMLConsumer;
import seatechit.msbgateway.consumer.SMSConsumer;
import seatechit.msbgateway.consumer.SalaryConsumer;
import seatechit.msbgateway.utils.CachedParam;
import seatechit.msbgateway.utils.ElementUtils;
import seatechit.msbgateway.utils.Global;

import com.ibm.broker.javacompute.MbJavaComputeNode;
import com.ibm.broker.plugin.MbElement;
import com.ibm.broker.plugin.MbException;
import com.ibm.broker.plugin.MbMessage;
import com.ibm.broker.plugin.MbMessageAssembly;
import com.ibm.broker.plugin.MbOutputTerminal;

public class MessageProcessor extends MbJavaComputeNode {
	final Logger logger = Logger.getLogger(MessageProcessor.class);
	final String app_version_test = "0.0";
	final String app_version_real = "1.0";

	public void evaluate(MbMessageAssembly inAssembly) throws MbException {
		// File log
		DOMConfigurator.configure("log4j.xml");
		// Khoi tao cache
		// TODO : Chuyen thanh false khi len production
		// CachedParam.getInstance(false);
		CachedParam.getInstance(false);

		MbOutputTerminal out = getOutputTerminal("out");

		MbMessage inMessage = inAssembly.getMessage();
		MbMessage outMessage = new MbMessage(inMessage);

		MbMessageAssembly outAssembly = new MbMessageAssembly(inAssembly, outMessage);
		if (logger.isDebugEnabled())
			logger.info(ElementUtils.getXMLContent(inMessage));
		settingRelationID(inMessage, outMessage);

		int errorCode = checkRequestDocument(inMessage);

		// Kienvt: phong truong hop deploy nham sang moi truong that check
		// version luu trong db
		if (!CachedParam.getSystemParam("APP_VERSION").equals(app_version_test)) {
			errorCode = Global.ERR_CM_REQ_DOC_VERSION_MISSING;
		}

		if (errorCode != Global.ERR_SYSTEM_OK) {
			ErrorInfo tempErrorInfo = CachedParam.mappingErrorCode(String.valueOf(errorCode), "", "");
			removeBodyElement(outMessage);
			buildInvalidRequestDocument(outMessage, tempErrorInfo);
		} else {
			removeBodyElement(outMessage);
			BaseConsumer objBaseConsumer = getRealConsumer(inMessage);
			objBaseConsumer.submit(inMessage, outMessage);
		}
		if (logger.isDebugEnabled())
			logger.info(ElementUtils.getXMLContent(outMessage));
		out.propagate(outAssembly);
	}

	/**
	 * 
	 * @param inMessage
	 * @return
	 */
	private BaseConsumer getRealConsumer(MbMessage inMessage) {
		String tran_code = ElementUtils.getXMLElementInStringValue(inMessage, Global.XML_HDR_FLD_TRAN_CODE);
		String tran_service_code = ElementUtils.getXMLElementInStringValue(inMessage, Global.XML_HDR_FLD_TRAN_SERVICE_CODE);
		if (tran_code.equalsIgnoreCase(Global.MSG_CM_SEND_EMAIL)) {
			return new EmailConsumer();
		} else if (tran_code.equalsIgnoreCase(Global.MSG_CM_SEND_SMS)) {
			return new SMSConsumer();
		} else if (tran_code.equalsIgnoreCase(Global.MSG_MP_INQUIRY_BILLPAYMENT_INFOR) || tran_code.equalsIgnoreCase(Global.MSG_MP_CREATE_BILLPAYMENT_TRANSACTION)) {
			return new SMLConsumer();
		} else if (tran_code.equalsIgnoreCase(Global.MSG_TR_TRANSFER_MONEY) && tran_service_code.equalsIgnoreCase("CSP200")) {
			return new SalaryConsumer();
		} else {
			return new SIBSConsumer();
		}
	}

	/**
	 * 
	 * @param outMessage
	 * @throws MbException
	 */
	@SuppressWarnings("unchecked")
	private void removeBodyElement(MbMessage outMessage) throws MbException {
		try {
			List<MbElement> lstOfElement = ((List<MbElement>) outMessage.evaluateXPath("/message/body"));
			if (lstOfElement.size() > 0) {
				lstOfElement.get(0).detach();
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	/**
	 * 
	 * @param inMessage
	 * @return
	 */
	private int checkRequestDocument(final MbMessage inMessage) {
		if (ElementUtils.getXMLContent(inMessage).length() > 0) {
			int errCode = Global.ERR_SYSTEM_OK;
			if (ElementUtils.getXMLElementInStringValue(inMessage, Global.XML_HDR_FLD_VERSION).length() == 0)
				errCode = Global.ERR_CM_REQ_DOC_VERSION_MISSING;
			if (ElementUtils.getXMLElementInStringValue(inMessage, Global.XML_HDR_FLD_MESSAGE_TYPE).length() == 0)
				errCode = Global.ERR_CM_REQ_DOC_MESSAGE_TYPE_MISSING;
			if (ElementUtils.getXMLElementInStringValue(inMessage, Global.XML_HDR_FLD_MESSAGE_SN).length() == 0)
				errCode = Global.ERR_CM_REQ_DOC_MESSAGE_SN_MISSING;
			// Kienvt:check do dai toi da cua du lieu
			if (ElementUtils.getXMLElementInStringValue(inMessage, Global.XML_HDR_FLD_SENDER_TRAN_SN).length() == 0
					|| ElementUtils.getXMLElementInStringValue(inMessage, Global.XML_HDR_FLD_SENDER_TRAN_SN).length() > 20)
				errCode = Global.ERR_CM_REQ_DOC_SENDER_TRAN_SN_MISSING;
			if (isValidAppSender(ElementUtils.getXMLElementInStringValue(inMessage, Global.XML_HDR_FLD_SENDER_ID)) == false)
				errCode = Global.ERR_CM_REQ_DOC_SENDER_ID_MISSING;
			// if
			// (!AppUtils.isValidDate(ElementUtils.getXMLElementInStringValue(inMessage,
			// Global.XML_HDR_FLD_SEND_DATE), Global.DEF_FORMAT_DATE_YYYYMMDD))
			// errCode = Global.ERR_CM_REQ_DOC_SEND_TIME_MISSING;
			if (ElementUtils.getXMLElementInStringValue(inMessage, Global.XML_HDR_FLD_SEND_TIME).length() == 0)
				errCode = Global.ERR_CM_REQ_DOC_SEND_TIME_MISSING;
			if (isValidTranCode(ElementUtils.getXMLElementInStringValue(inMessage, Global.XML_HDR_FLD_TRAN_CODE)) == false)
				errCode = Global.ERR_CM_REQ_DOC_TRAN_CODE_MISSING;
			if (ElementUtils.getXMLElementInStringValue(inMessage, Global.XML_HDR_FLD_RECEIVER_ID).length() == 0)
				errCode = Global.ERR_CM_REQ_DOC_RECEIVER_ID_MISSING;
			return errCode;
		} else {
			return Global.ERR_CM_DOC_FORMAT_INCORRECT;
		}
	}

	/**
	 * 
	 * @param appSender
	 * @return
	 */
	private boolean isValidAppSender(String appSender) {
		ArrayList<String> arrAppSender = new ArrayList<String>();
		arrAppSender.add(Global.APP_SENDER_SMS);
		arrAppSender.add(Global.APP_SENDER_MOBILE_APP);
		arrAppSender.add(Global.APP_SENDER_MOBILE_WAP);
		arrAppSender.add(Global.APP_SENDER_IBS);
		return arrAppSender.contains(appSender == null ? "" : appSender);
	}

	/**
	 * 
	 * @param tranCode
	 * @return
	 */
	private boolean isValidTranCode(String tranCode) {
		ArrayList<String> arrTranCode = new ArrayList<String>();
		arrTranCode.add(Global.MSG_CM_SEND_SMS);
		arrTranCode.add(Global.MSG_CM_SEND_EMAIL);
		arrTranCode.add(Global.MSG_CM_INQUIRY_CIF_INFOR);
		arrTranCode.add(Global.MSG_CM_INQUIRY_CIF_ACCOUNTS);
		arrTranCode.add(Global.MSG_CM_INQUIRY_MINISTATEMENT_BY_ACCOUNT);
		arrTranCode.add(Global.MSG_OS_CREATE_FD_ACCOUNT);
		arrTranCode.add(Global.MSG_OS_CREATE_FD_RECEIPT);
		arrTranCode.add(Global.MSG_OS_TRANSFER_FD_RECEIPT);
		arrTranCode.add(Global.MSG_OS_SETTLEMENT_FD_ACCOUNT);
		arrTranCode.add(Global.MSG_MP_CREATE_BILLPAYMENT_TRANSACTION);
		arrTranCode.add(Global.MSG_MP_INQUIRY_BILLPAYMENT_INFOR);
		arrTranCode.add(Global.MSG_MP_INQUIRY_CREDITCARD_BILL_INFOR);
		arrTranCode.add(Global.MSG_MP_PAYMENT_CREDITCARD_BILL);
		arrTranCode.add(Global.MSG_CS_ACTIVATED_ATMCARD);
		arrTranCode.add(Global.MSG_CS_APPLICATION_CREDITCARD);
		arrTranCode.add(Global.MSG_TR_TRANSFER_MONEY);
		arrTranCode.add(Global.MSG_TR_CREATE_CASHFLOW_TRANSACTION);
		arrTranCode.add(Global.MSG_TR_CANCEL_SCHEDULE_TRANSFER);
		arrTranCode.add(Global.MSG_TR_CANCEL_CASHFLOW_TRANSACTION);
		arrTranCode.add(Global.MSG_LN_PAYMENT_LN_TRANSACTION);
		arrTranCode.add(Global.MSG_FX_CREATE_EXCHANGEMONEY_TRANSACTION);
		arrTranCode.add(Global.MSG_TF_SEND_REPORT_TO_PAYMENTCENTER);
		return arrTranCode.contains(tranCode == null ? "" : tranCode);
	}

	/**
	 * 
	 * @param tranServiceCode
	 * @return
	 */
	// private boolean checkTranServiceCode(String tranServiceCode) {
	// return true;
	// }
	/**
	 * 
	 * @param outMessage
	 * @param inErrorInfo
	 */
	private void buildInvalidRequestDocument(MbMessage outMessage, ErrorInfo inErrorInfo) {
		String xpath = "/message/head/field[@name='%s']";
		try {
			ElementUtils.getXMLElement(outMessage, String.format(xpath, "resp_code")).setValue(inErrorInfo.getErrorCode());
			ElementUtils.getXMLElement(outMessage, String.format(xpath, "resp_msg")).setValue(inErrorInfo.getErrorMessage());
		} catch (MbException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 
	 * @param inMessage
	 * @param outMessage
	 * @throws MbException
	 */
	private void settingRelationID(final MbMessage inMessage, MbMessage outMessage) throws MbException {
		MbElement mbInElement = inMessage.getRootElement();
		mbInElement = (MbElement) ((List) mbInElement.evaluateXPath("MQMD/MsgId")).get(0);
		MbElement mbOutElement = outMessage.getRootElement();
		mbOutElement = (MbElement) ((List) mbOutElement.evaluateXPath("MQMD/CorrelId")).get(0);
		mbOutElement.setValue((byte[]) mbInElement.getValue());
	}
}
